package de.herzog.bbp.view.javafx;

import javafx.scene.Node;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.util.StringConverter;

import org.controlsfx.validation.Severity;
import org.controlsfx.validation.ValidationSupport;

import de.herzog.bbp.view.bean.AbstractBean;

public abstract class TableCellUtils {

	private static final ValidationSupport VALIDATION_SUPPORT = new ValidationSupport();

	private static <S extends AbstractBean, T> String getItemText(final EditingTableCell<S, T> cell,
			final StringConverter<T> converter) {
		return converter == null ? cell.getItem() == null ? "" : cell.getItem().toString() : converter.toString(cell
				.getItem());
	}

	static <S extends AbstractBean, T> void updateItem(final EditingTableCell<S, T> cell,
			final StringConverter<T> converter, final Validator validator, final TextField textField) {
		if (cell.isEmpty()) {
			cell.setText(null);
			cell.setGraphic(null);
		} else {
			String text = getItemText(cell, converter);
			if (cell.isEditing()) {
				if (textField != null) {
					textField.setText(text);
				}
				cell.setText(null);
			} else {
				cell.setText(text);
				cell.getStyleClass().remove(ValidatedTextField.STLYE_CLASS_INVALID);
				if (!validator.isValid(text)) {
					cell.getStyleClass().add(ValidatedTextField.STLYE_CLASS_INVALID);
				}
				cell.getStyleClass().remove(ValidatedTextField.STLYE_CLASS_CHECKERROR);
				TableView<S> tableView = cell.getTableView();
				int index = cell.getTableRow().getIndex();
				S rowBean = tableView.getItems().get(index);
				String columnId = cell.getTableColumn().getId();
				if (rowBean.hasCheckError(columnId)) {
					cell.getStyleClass().add(ValidatedTextField.STLYE_CLASS_CHECKERROR);
				}
				cell.setGraphic(null);
			}
		}
	}
	
	static <S extends AbstractBean, T> void startEdit(final EditingTableCell<S, T> cell,
			final StringConverter<T> converter, final TextField textField) {
		if (textField != null) {
			textField.setText(getItemText(cell, converter));
		}
		cell.setText(null);
		cell.setGraphic(textField);
		textField.selectAll();
		textField.requestFocus();
	}

	static <S extends AbstractBean, T> void cancelEdit(final EditingTableCell<S, T> cell,
			final StringConverter<T> converter, Node graphic) {
		cell.setText(getItemText(cell, converter));
		cell.setGraphic(graphic);
	}

	static <S extends AbstractBean, T> TextField createTextField(final EditingTableCell<S, T> cell,
			final StringConverter<T> converter, final Validator validator,
			final AutoCompleteListFactory<S, T> autoCompleteListFactory) {
		final TextField textField = new ValidatedTextField<T>(validator, cell);
		VALIDATION_SUPPORT.registerValidator(textField, org.controlsfx.validation.Validator.createEqualsValidator(
				"Unbekannter Wert", Severity.WARNING, autoCompleteListFactory.getList()));
		ValidationSupport.setRequired(textField, false);
		textField
				.setOnAction(actionEvent -> {
					if (converter == null) {
						String msg = "Attempting to convert text input into Object, but provided  StringConverter is null. Be sure to set a StringConverter in your cell factory.";
						throw new IllegalStateException(msg);
					}
					cell.commitEdit(converter.fromString(textField.getText()));
					actionEvent.consume();
				});
		textField.setOnKeyReleased(keyEvent -> {
			if (keyEvent.getCode() == KeyCode.ESCAPE) {
				cell.cancelEdit();
				keyEvent.consume();
			}
		});
		return textField;
	}
}
